package model

import (
	"encoding/json"
	"fmt"

	"gitee.com/bjf-fhe/apinx/openapi"
	"github.com/getkin/kin-openapi/openapi3"
)

type Transformer struct {
	updateWhenChanged bool
	Encrypter         *SmartEncrypter
}

func NewTransformer(updateWhenChanged bool) *Transformer {
	return &Transformer{
		updateWhenChanged: updateWhenChanged,
		Encrypter:         &SmartEncrypter{},
	}
}

func (g *Transformer) TransformValueVersa(def *openapi3.Schema, value interface{}) (bool, interface{}, error) {
	return g.transformValue(def, value, true)
}

func (g *Transformer) TransformValue(def *openapi3.Schema, value interface{}) (bool, interface{}, error) {
	return g.transformValue(def, value, false)
}

func (g *Transformer) transformValue(def *openapi3.Schema, value interface{}, versa bool) (bool, interface{}, error) {
	rawRule, ok := def.Extensions["x-bjf-encrypter"]
	var rule string
	var hasChange = false
	if !ok || rawRule == "" {
		//如果没有定义，则自动匹配，将自动匹配的结果写入到定义中，以便下次直接使用
		hasChange = true
		//需要智能排查
		rule = g.Encrypter.Match(value)
		fmt.Println("match result", rule, value)
		if def.Extensions == nil {
			def.Extensions = make(map[string]interface{})
		}
		def.Extensions["x-bjf-encrypter"] = rule
		if rule == "-" {
			return true, value, nil
		}
	} else {
		switch tr := rawRule.(type) {
		case string:
			rule = tr
		case json.RawMessage:
			err := json.Unmarshal(tr, &rule)
			if err != nil {
				return false, value, err
			}
		default:
			return false, value, fmt.Errorf("x-bjf-encrypter valued by invalid value:(%T)%v", rawRule, rawRule)
		}
		if rule == "-" {
			return false, value, nil
		}
	}
	var result interface{}
	var err error
	if versa {
		result, err = g.Encrypter.HandleVersaByRule(rule, value)
	} else {
		result, err = g.Encrypter.HandleByRule(rule, value)
	}
	return hasChange, result, err
}

func (g *Transformer) CreateResponseIfNotDefined() openapi.ActionTypeWhenNotDefined {
	if g.updateWhenChanged {
		return openapi.CreateDefWhenNotDefined
	} else {
		return openapi.ThrowErrorOfNotDefined
	}
}

func (g *Transformer) CheckParameter(name string, schema *openapi3.Schema, value string) (bool, interface{}, error) {
	if schema.Enum != nil {
		var isAllowed = false
		for _, v := range schema.Enum {
			if value == fmt.Sprintf("%v", v) {
				isAllowed = true
				break
			}
		}
		if !isAllowed {
			return false, nil, fmt.Errorf("参数%s要求为是%v中的一项，必须传入值为%s", name, schema, value)
		}
	}
	return g.TransformValueVersa(schema, value)
}
